import TSpace.*;

import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.util.Random;

public class TSClient
{
    private TupleSpace tsImpl;
    private ORB orb;
    private int random_counter;

    public TSClient(String args[], int spaceNumber)
    {
        try
        {
            // create and initialize the ORB
            orb = ORB.init(args, null);

				// initialize a random counter
				random_counter = (new Random()).nextInt() << 16;

            // get the root naming context
            org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
            // Use NamingContextExt instead of NamingContext. This is 
            // part of the Interoperable naming Service.  
            NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

            // resolve the Object Reference in Naming
            String name = "TupleSpace" + spaceNumber;
            tsImpl = TupleSpaceHelper.narrow(ncRef.resolve_str(name));

            System.out.println("Obtained a handle on server object: " + tsImpl);
        }
        catch (Exception e)
        {
            System.out.println("ERROR : " + e) ;
            e.printStackTrace(System.out);
        }
    }

	public boolean write(java.lang.Object e1, TupleType typeE1)
	{
		++random_counter;
		Any eOne = orb.create_any();
		Any eTwo = orb.create_any();
		Any eThree = orb.create_any();
		setAny(eOne, e1, typeE1);
		Tuple tuple = new Tuple((short) 1, eOne, eTwo, eThree);
		TupleRequest tupleRequest = new TupleRequest(random_counter, tuple);
		return tsImpl.write(tupleRequest);
	}

	public boolean write(java.lang.Object e1, TupleType typeE1, java.lang.Object e2, TupleType typeE2)
	{
		++random_counter;
		Any eOne = orb.create_any();
		Any eTwo = orb.create_any();
		Any eThree = orb.create_any();
		setAny(eOne, e1, typeE1);
		setAny(eTwo, e2, typeE2);
		Tuple tuple = new Tuple((short) 2, eOne, eTwo, eThree);
		TupleRequest tupleRequest = new TupleRequest(random_counter, tuple);
		return tsImpl.write(tupleRequest);
	}

	public boolean write(java.lang.Object e1, TupleType typeE1, java.lang.Object e2,
	                     TupleType typeE2, java.lang.Object e3, TupleType typeE3)
	{
		Any eOne = orb.create_any();
		Any eTwo = orb.create_any();
		Any eThree = orb.create_any();
		setAny(eOne, e1, typeE1);
		setAny(eTwo, e2, typeE2);
		setAny(eThree, e3, typeE3);
		Tuple tuple = new Tuple((short) 3, eOne, eTwo, eThree);
		TupleRequest tupleRequest = new TupleRequest(random_counter, tuple);
		return tsImpl.write(tupleRequest);
	}
	
	private void setAny(Any anAny, java.lang.Object element, TupleType typeElement)
	{
		System.out.println("TSClient::setAny");
		
		switch (typeElement)
		{
			case INT:
				anAny.insert_long(((Integer) element).intValue());
				break;
			case STRING:
				anAny.insert_string((String) element);
				break;
			case LONG:
				anAny.insert_longlong(((Long) element).longValue());
				break;
			case CHAR:
				anAny.insert_char(((Character) element).charValue());
				break;			
			case SHORT:
				anAny.insert_short(((Short) element).shortValue()); 
				break;

			default:
				throw new RuntimeException();		
		}
	}

	public Tuple read(TupleType typeE1, TupleType typeE2, TupleType typeE3)
	{
		TupleTemplate aTemplate = new TupleTemplate();

		aTemplate.requestNumber = -1;
		
		aTemplate.Types = new String[3];
		aTemplate.Values = new String[3];
		
		aTemplate.Types[0] = TupleTypeMap.tupleTypeToString(typeE1); 
		aTemplate.Types[1] = TupleTypeMap.tupleTypeToString(typeE2);
		aTemplate.Types[2] = TupleTypeMap.tupleTypeToString(typeE3);
		
		aTemplate.Values[0] = new String();
		aTemplate.Values[1] = new String();
		aTemplate.Values[2] = new String();
		
		return tsImpl.read(aTemplate);
	}

	public Tuple take(TupleType typeE1, TupleType typeE2, TupleType typeE3)
	{
		TupleTemplate aTemplate = new TupleTemplate();

		++random_counter;
		aTemplate.requestNumber = random_counter;
		
		aTemplate.Types = new String[3];
		aTemplate.Values = new String[3];
		
		aTemplate.Types[0] = TupleTypeMap.tupleTypeToString(typeE1); 
		aTemplate.Types[1] = TupleTypeMap.tupleTypeToString(typeE2);
		aTemplate.Types[2] = TupleTypeMap.tupleTypeToString(typeE3);
		
		aTemplate.Values[0] = new String();
		aTemplate.Values[1] = new String();
		aTemplate.Values[2] = new String();
		
		return tsImpl.take(aTemplate);
	}

	public Tuple read(TupleType typeE1, TupleType typeE2, TupleType typeE3, String tuple1, String tuple2, String tuple3)
	{
		TupleTemplate aTemplate = new TupleTemplate();
		
		aTemplate.requestNumber = -1;
		
		aTemplate.Types = new String[3];
		aTemplate.Values = new String[3];
		
		aTemplate.Types[0] = TupleTypeMap.tupleTypeToString(typeE1); 
		aTemplate.Types[1] = TupleTypeMap.tupleTypeToString(typeE2);
		aTemplate.Types[2] = TupleTypeMap.tupleTypeToString(typeE3);
		
		aTemplate.Values[0] = tuple1;
		aTemplate.Values[1] = tuple2;
		aTemplate.Values[2] = tuple3;
		
		return tsImpl.read(aTemplate);
	}

	public Tuple take(TupleType typeE1, TupleType typeE2, TupleType typeE3, String tuple1, String tuple2, String tuple3)
	{
		TupleTemplate aTemplate = new TupleTemplate();
		
		++random_counter;
		aTemplate.requestNumber = random_counter;
		
		aTemplate.Types = new String[3];
		aTemplate.Values = new String[3];
		
		aTemplate.Types[0] = TupleTypeMap.tupleTypeToString(typeE1); 
		aTemplate.Types[1] = TupleTypeMap.tupleTypeToString(typeE2);
		aTemplate.Types[2] = TupleTypeMap.tupleTypeToString(typeE3);

		aTemplate.Values[0] = tuple1;
		aTemplate.Values[1] = tuple2;
		aTemplate.Values[2] = tuple3;
		
		return tsImpl.take(aTemplate);
	}

	public Tuple[] readAll()
	{
		return tsImpl.readAll();
	}

	public boolean ping()
	{
		return tsImpl.ping();
	}

	public TupleSpace getTupleSpace()
	{
		return tsImpl;
	}
}

